home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue25 / compress / COMPRESS.ZIP / ARC2BLOB.PAS next >
Encoding:
Pascal/Delphi Source File  |  1997-07-09  |  5.6 KB  |  124 lines

  1. (*  ARC2BLOB.PAS for TCompress V3.0 (no change from V2.5 except para 4 in comments)
  2.  
  3. This code is designed to be dropped into the COMPDEMO application, adding
  4. one new routine (LoadArchivedFileToBlobStream) and replacing one existing one
  5. (CDBImage1DragDrop).
  6.  
  7. It shows what is probably the most efficient way to load compressed data from
  8. a file archive to a blob field, without using an intermediate file as
  9. COMPDEMO currently does.
  10.  
  11. Keep in mind that both this and the ARC2MEM code require manipulation of some
  12. of the TCompress data structures... Unlike ARC2MEM, this approach doesn't
  13. require a large memory buffer (because no expansion step), but does require
  14. more knowledge of the TCompress data structures.
  15.  
  16. *** In TCompress 3.0, an alternative (and far easier) approach would be to use
  17. the new ExpandStreamFromArchive routine. Because this would be writing
  18. *expanded* data to the blob (which hence must be recompressed for storage),
  19. two important points would apply if you used it:
  20. 1. It would not be as efficient as this routine, which copies the data in
  21.    compressed form
  22. 2. You must pass a TCBlobstream to the above method, NOT the TBlobstream which
  23.    this routine uses.
  24. ExpandStreamFromArchive would be ideal, however, if you were loading a regular
  25. field or Delphi stream-based object from an archive (e.g. a TDBImage)
  26. *)
  27.  
  28. { Example of Expanding a file DIRECTLY from an archive to a COMPRESSED field's blobstream.
  29.   Important note: we are NOT expanding the data at all, thus we are actually bypassing
  30.   all the expansion/compression stuff and writing directly to the underlying database }
  31. procedure TForm1.LoadArchivedFileToBlobStream(bs:TBlobstream;filepath:String);
  32. var fs: TFilestream;
  33.     cfinfo: TCompressedFileInfo;
  34.     fHeader: TCompressedFileHeader; { file header so we can get compression mode }
  35.     aheader: TCompressHeader;       { archive header required for Blobstream     }
  36.     cmode: string;
  37. begin
  38.   cfinfo := TCompressedFileInfo(FileList.objects[FileList.indexof(filepath)]);
  39.   fs:=TFileStream.Create(archivefile.text,fmOpenRead or fmShareExclusive); { just want to READ it... }
  40.   try
  41.      fs.read(aheader,sizeof(aheader));  { quick way to initialize archive header }
  42.      fs.seek(cfinfo.Position,0);        { start of FILE header within archive }
  43.      fs.read(fheader, sizeof(fheader)); { let's have it }
  44.      fs.seek(fheader.FilenameLength,1); { skip the filename which is stored next }
  45.  
  46.      { Now the tricky part -- we need to store a valid 3-char compression ID
  47.        in our archive header -- here's the best approach: }
  48.  
  49.      if fheader.compressedmode<>coNone then { coNone won't GET a header... }
  50.      begin
  51.        case fheader.compressedmode of
  52.           coLZH: cmode := 'LZH';
  53.           coRLE: cmode := 'RLE';
  54.           coCustom: cmode := 'CUS'; { CHANGE this if you use a different ID! }
  55.        end;
  56.        with aheader do  { ComID is already set by the read we did }
  57.        begin
  58.           Fullsize:=fheader.FullSize;
  59.           ArchiveType:=caSingle;
  60.           CheckSum := fheader.checksum;
  61.           Move(cmode[1],ComMethodID,sizeof(ComMethodID)); { get precisely the bytes we want... }
  62.        end;
  63.        bs.write(aheader,sizeof(aheader)); { set up the header }
  64.      end;
  65.      bs.copyFrom(fs,Fheader.compressedsize); { now get the raw (compressed) data! }
  66.      bs.truncate; { in case it started out larger... }
  67.   finally
  68.      fs.free
  69.   end;
  70. end;
  71.  
  72. { Examples of setting/loading/shifting image blobs using the above routine }
  73. procedure TForm1.CDBImage1DragDrop(Sender, Source: TObject; X, Y: Integer);
  74. var filepath: String;
  75.      cbs: TCBlobStream; { for loading image from an archived file }
  76. begin
  77.    if Source=Sender then exit; { nowt to do }
  78.    if (Sender is TCDBImage) and (not Table1.active) then
  79.    begin
  80.      showmessage('Can''t do this unless table has been opened...');
  81.      exit;
  82.    end;
  83.  
  84.   Screen.Cursor := crHourGlass;
  85.   if (Source is TImage) and (Sender is TCDBImage) then
  86.      CDBImage1.picture.bitmap.Assign(Image1.Picture.bitmap)
  87.   else if (Source is TCDBImage) and (Sender is TImage) then
  88.      Image1.picture.bitmap.Assign(CDBImage1.Picture.Bitmap)
  89.   else
  90.   begin   { Have we got an image? }
  91.      filepath := '';
  92.      if (Source is TListBox) and (Listbox1.selcount = 1) then
  93.       filepath:=ListBox1.Items[Listbox1.ItemIndex] { archive list }
  94.      else if (Source is TFileListBox) and (FL.selcount=1) then
  95.         filepath:=FL.Items[FL.ItemIndex]; { file list }
  96.      if ExtractFileExt(filepath)<>'.bmp' then
  97.         showmessage('Must be a .BMP file...')
  98.      else                                     { ok, here we go... }
  99.      if Source is TFileListBox then { just load from file... }
  100.        if Sender is TImage then
  101.           Image1.Picture.Bitmap.LoadFromfile(filepath)
  102.        else
  103.           CDBImage1.Picture.Bitmap.LoadFromFile(filepath)
  104.      else { source must be our archive file... }
  105.      begin
  106.        if Sender is TImage then
  107.            { Fastest way is using LoadArchivedFileToMemory approach per ARC2MEM.PAS }
  108.        else
  109.        begin { here is where we use our direct access routine... }
  110.          cbs:=TCBlobStream.Create(CDBImage1.CField,bmWrite);      { we ARE going to update but... }
  111.          try
  112.            LoadArchivedFileToBlobstream(cbs.Blobstream,filepath); { NOT via expansion/compression }
  113.          finally  { See the HELP notes on the Blobstream property for caveats }
  114.            cbs.free
  115.          end;
  116.        end
  117.      end;
  118.   end;
  119.   if Table1.active and Table1.Modified then Table1.post; { save immediately if updated }
  120.   if not Image1.Picture.Bitmap.Empty then Memo1.visible := False; { got a piccy showing... }
  121.   Screen.Cursor := crDefault;
  122. end;
  123.  
  124.